#ifndef _COMPAREFEATURES_H_
#define _COMPAREFEATURES_H_

#include "Opencv.h"
#include "SPRH2d.h"
#include "matching.h"
#include "combineImage.h"
#include "stateManipulator.h"
#define CV_COMP_MANHATTAN 15

struct histFeatures
{
  CvHistogram *hist;
  int hn;
};

struct partFeatures
{
  int num;
  int fnum;
  float *x;
  float *y;
  float *len;
  float *ang;

  cv::Mat img;
};

struct featureVec
{
  int stateNum;
  int imageNum;
  std::vector<float> features;
};


class compareCloth
{

 public:
    char dirname[128];
  vector<float> threVec;
  float sprhThre;
  float histThre;
  float partThre;
  std::vector<SPRHfeature> sprhTrain;
  std::vector<histFeatures> histTrain;
  std::vector<partFeatures> partTrain;

  std::vector<featureVec> sprhTrainVec, histTrainVec, partTrainVec;

  int need_to_match_Num;
  std::list<int> indexlist;
  int compareNum;
  int checkStateResult;
  int currentState;
  int tempState;
  int eachImageNum;
  stateManipulator sm;
  int numOfFeature;
  int tempImageNum;
  cv::Mat resultMatchImg;


 public:
  //compareCloth(const char* const ch, int in, int stateNum)
  compareCloth()
    {
      //sm.initProbabilityMap(stateNum);
      //sm.initAliasVector(stateNum);
      //dirname = ch;
      eachImageNum = 0;
      currentState = 0;
      sprhThre = 0.35;
      histThre = 0.45;
      partThre = 0.35;
      numOfFeature = 3;
      need_to_match_Num = 2;

      for(int i = 0; i<need_to_match_Num; i++)
	{
	  indexlist.push_back(-1);
	}
      for(int i = 0; i<numOfFeature; i++)
	{
	  threVec.push_back(0);
	}
      threVec[0] = 0.35;
      threVec[1] = 0.45;
      threVec[2] = 0.35;
      //sm = &stateManipulator(stateNum);
      /* sm.initProbabilityMap(stateNum); */
      /* sm.initAliasVector(stateNum); */



      //init(ch, in,stateNum);
      tempImageNum = 1;

      resultMatchImg = cv::Mat(384,512,CV_32FC3);

    }

  ~compareCloth()
    {
      /* sprhTrain.clear(); */
      /* histTrain.clear(); */
      /* partTrain.clear(); */
      sprhTrainVec.clear();
      histTrainVec.clear();
      partTrainVec.clear();
    }

  void init(const char* const ch, int in, int stateNum);

  void setThreshold(float sprh, float hist, float part);

  void setThreVec(vector<float> inThreVec);

  void getThreshold(float &sprh, float &hist, float &part);

  void getThreVec(vector<float> *outThreVec);

  int convertStateNum(int num);

  int calcStateNum(int num);

  int calcImageNum(int num);

  bool compareStateNum(int num);

  int getState(void);

  void setState(int num);

  int getTempState(void){return tempState;};

  void setTempState(int num){tempState = num;};


  void showResult(vector< vector< pair<int,float> > > result, cv::Mat srcimg, cv::Mat &output);

  void showResultVec(vector< vector< pair<pair <int,int>,float> > > result, cv::Mat srcimg, cv::Mat &output);

  void stateMatch(int imnum, std::vector<Point2f> flowPoint, std::vector<Point2f> flowScale, cv::Mat input);

  void stateVecMatch(int imageNum, std::vector<Point2f> flowPoint, std::vector<Point2f> flowScale, cv::Mat input, cv::Mat &output);

  float calcFeatureDist(vector<float> currentVec, vector<float> learnedVec, int method);

  void compareFeatureVec(vector<float> currentVec, std::vector<featureVec> trainVec, std::vector<pair<pair<int,int>, float> > *result, int method);

  void compareSprh(int imnum,const std::vector<Point2f> flowPoint, const std::vector<Point2f> flowScale, std::vector<SPRHfeature> sprh_train, std::vector<pair<int, float> > *result);

  void compareHist(int imn, std::vector<Point2f> flowPoint, std::vector<Point2f> flowScale, cv::Mat input, std::vector<histFeatures> hlist, std::vector<pair<int, float> > *result);

  void comparePart(int imn, vector< pair<P2d,P2d> > vals, cv::Mat input, std::vector<partFeatures> part_train, std::vector<pair<int, float> > *result);

  void compareMean(int imn, vector< pair<P2d,P2d> > vals, cv::Mat input, std::vector<partFeatures> part_train, std::vector<pair<int, float> > *result);

  void genfiles(int imnum, std::vector<Point2f> flowPoint, std::vector<Point2f> flowScale, cv::Mat input);

  void genVecFiles(std::vector<Point2f> flowPoint, std::vector<Point2f> flowScale, cv::Mat input);

  void genImageFile(int imnum, cv::Mat input);

  void genImageFileVec(cv::Mat input);

  void genSprhFile(int imnum, const std::vector<Point2f> flowPoint, const std::vector<Point2f> flowScale);

  void genHistFile(int imnum, std::vector<Point2f> flowScale, std::vector<Point2f> flowPoint, cv::Mat input);

  int genPartFile(int imnum, const std::vector< pair<P2d,P2d> > vals, const std::vector< pair<P2d,P2d> > selected, cv::Mat input);

  int genAllFlowFile(const std::vector<Point2f> flowPoint, const std::vector<Point2f> flowScale);

  void genSprhVec(const std::vector<Point2f> flowPoint, const std::vector<Point2f> flowScale, vector<float> *sprhVec);

  void genHistVec(const std::vector<Point2f> flowPoint, const std::vector<Point2f> flowScale, cv::Mat input, vector<float> *histVec);

  void genPartVec(const std::vector<Point2f> flowPoint, const std::vector<Point2f> flowScale, cv::Mat input, vector<float> *partVec);

  void saveFeatureVec(char *filename, vector<float> features);

  std::vector<SPRHfeature> loadSprhFeatures(void);

  std::vector<histFeatures> loadHistogram(void);

  std::vector<partFeatures> loadPartFeatures(void);

  std::vector<featureVec> loadFeatureVec(char *filename);

  int displayResult(std::vector<pair<int, float> > result, char *windowname, float shre, cv::Mat input);

  int displayResult2(std::vector<pair<int, float> > result, char *windowname, float shre, cv::Mat input, int imnum);

  int displayResultVec(std::vector<pair< pair<int,int>, float> > result, char *windowname, float shre, cv::Mat input, int imnum);

  void sumResult(vector< vector< pair<int,float> > > result, float &maxSum, int &maxIndex);

  void sumVecResult(vector< vector< pair<pair<int,int>,float> > > result, float &maxSum, pair<int,int> &maxIndex);

  void sumVecResult_withStateManipulator(vector< vector< pair<pair<int,int>,float> > > result, float &maxSum, pair<int,int> &maxIndex);

  int getCheckStateResult();

  int checkState(int matchState);

  void convertOldFile2NewFile();

  int showDatabaseFlow(int stateNum, int imageNum);

  void getMatchImg(cv::Mat &output){resultMatchImg.copyTo(output);};

};

#endif
